package org.shiro.auth.controller;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;

@Configuration
public class ShiroConfig {

  @Bean
  public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  }

  /**
   * ShiroDialect，为了在thymeleaf里使用shiro的标签的bean
   *
   * @return
   */
  @Bean
  public ShiroDialect shiroDialect() {
    return new ShiroDialect();
  }

  @Bean
  ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    shiroFilterFactoryBean.setLoginUrl("/login");
    shiroFilterFactoryBean.setSuccessUrl("/index");
    shiroFilterFactoryBean.setUnauthorizedUrl("/403");
    LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

    filterChainDefinitionMap.put("/login", "anon");
    filterChainDefinitionMap.put("/index", "authc");
    filterChainDefinitionMap.put("/css/**", "anon");
    filterChainDefinitionMap.put("/js/**", "anon");
    filterChainDefinitionMap.put("/fonts/**", "anon");
    filterChainDefinitionMap.put("/img/**", "anon");
    filterChainDefinitionMap.put("/docs/**", "anon");
    filterChainDefinitionMap.put("/druid/**", "anon");
    filterChainDefinitionMap.put("/upload/**", "anon");
    filterChainDefinitionMap.put("/files/**", "anon");
    filterChainDefinitionMap.put("/tmp/**", "anon");
    filterChainDefinitionMap.put("/files/resultReport/**", "anon");
    filterChainDefinitionMap.put("/logout", "logout");
    filterChainDefinitionMap.put("/", "anon");
    filterChainDefinitionMap.put("/blog", "anon");
    filterChainDefinitionMap.put("/rest/**", "anon");
    filterChainDefinitionMap.put("/v2/**", "anon");
    filterChainDefinitionMap.put("/blog/open/**", "anon");
    filterChainDefinitionMap.put("/screening/wechat/**", "anon");
    filterChainDefinitionMap.put("/wxdazd/**", "anon");
    filterChainDefinitionMap.put("/wx/**", "anon");
    filterChainDefinitionMap.put("/creditOnline/**", "anon");
    filterChainDefinitionMap.put("/fy/goodsMessage/rest/**", "anon");
    filterChainDefinitionMap.put("/**", "anon");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
  }

  @Bean
  public SecurityManager securityManager() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(new UserRealm());
    securityManager.setSessionManager(sessionManager());
    return securityManager;
  }

  /**
   * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持;
   *
   * @param securityManager
   * @return
   */
  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    return authorizationAttributeSourceAdvisor;
  }

  /**
   * shiro session的管理
   */
  @Bean
  public DefaultWebSessionManager sessionManager() {
    DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
    sessionManager.setGlobalSessionTimeout(86400 * 1000);
    sessionManager.setSessionDAO(new MemorySessionDAO());
    Collection<SessionListener> listeners = new ArrayList<SessionListener>();
    sessionManager.setSessionListeners(listeners);
    return sessionManager;
  }

}
